#pragma once
#include <iostream>
#include <string>
#include <unordered_map>
#include <sys/epoll.h>
#include <unistd.h>

#define SIZE 128
#define NUM 64

struct Event;
class Reactor;
typedef int (*callback_t)(Event*);
struct Event
{
public:
    int sock;
    std::string inbuffer;  //输入缓冲区
    std::string outbuffer; //输出缓冲区
    
    callback_t recver;
    callback_t sender;
    callback_t errorer;

    Reactor* R; //定义一个回指Reactor的指针

    Event() : sock(-1)
    {
        recver = nullptr;
        sender = nullptr;
        errorer = nullptr;
        R = nullptr;
    }

    //注册事件
    void RegisterEvent(callback_t rcv, callback_t sed, callback_t err)
    {
        recver = rcv;
        sender = sed;
        errorer = err;
    }

    ~Event(){}
};

class Reactor
{
public:
    int efd;
    std::unordered_map<int, Event*> Events;
    Reactor() : efd(-1)
    {}

    //创建Epoll模型
    void CreateEpoll()
    {
        efd = epoll_create(SIZE);
        if(efd < 0)
        {
            std::cerr << "epoll_create error" << std::endl;
            return;
        }
        std::cout << "CreateEpoll success " << efd << std::endl;
    }

    //插入事件
    bool InsertEvent(Event* evl, uint32_t events)
    {
        struct epoll_event ev;
        ev.data.fd = evl->sock;
        ev.events = events;
        int ret = epoll_ctl(efd, EPOLL_CTL_ADD, evl->sock, &ev);
        if(ret < 0)
        {
            std::cout << "epoll_ctl error" << std::endl;
            return false;
        }
        std::cout << "insertEvent success " << evl->sock << std::endl;
        Events.insert({evl->sock, evl});

        return true;
    }

    //删除事件
    void DeleteEvent(Event* ev)
    {
        int sock = ev->sock;
        auto lt = Events.find(sock);
        if(lt != Events.end())
        {
            std::cout << "连接关闭了 " << sock << std::endl;
            epoll_ctl(efd, EPOLL_CTL_DEL, sock, nullptr);
            close(sock);
            Events.erase(lt);
            delete ev;
        }
    }

    //修改
    bool EnableRW(int sock, bool rd, bool wd)
    {
        struct epoll_event ev;
        ev.events = EPOLLET | (rd ? EPOLLIN : 0) | (wd ? EPOLLOUT : 0);
        ev.data.fd = sock;

        if(epoll_ctl(efd, EPOLL_CTL_MOD, sock, &ev) < 0)
        {
            std::cerr << "epoll_ctl mod event failed" << std::endl;
            return false;
        }
        return true;
    }

    bool isSockOk(int sock)
    {
        auto lt = Events.find(sock);
        if(lt == Events.end())
            return false;
        else
            return true;
    }

    //派发器
    void Dispatcher(int timeout)
    {
        struct epoll_event evs[NUM];
        int n = epoll_wait(efd, evs, NUM, timeout);
        for(int i = 0;i < n;++i)
        {
            //发送错误
            if(evs[i].events & EPOLLERR)
                evs[i].events |= (EPOLLIN | EPOLLOUT);
            //被挂断
            if(evs[i].events & EPOLLHUP)
                evs[i].events |= (EPOLLIN | EPOLLOUT);
            
            //读事件就绪
            int fd = evs[i].data.fd;
            if(evs[i].events & EPOLLIN)
            {
                std::cout << "读事件就绪啦 " << fd << std::endl;
                if(isSockOk(fd) && Events[fd]->recver)
                    Events[fd]->recver(Events[fd]);
            }
            //写事件就绪
            if(evs[i].events & EPOLLOUT)
            {
                std::cout << "写事件就绪啦 " << fd << std::endl;
                if(isSockOk(fd) && Events[fd]->sender)
                    Events[fd]->sender(Events[fd]);
            }
        }
    }

    ~Reactor(){}
};